from typing import Tuple
import numpy as np
import pandas as pd
import os
import math
import sys
import random

data_files = [('db', './data/1-数据库健康度数据.csv'),
            ('bus', './data/2-业务健康度数据.csv'),
            ('app', './data/3-应用健康度数据.csv'),
            ('mid', './data/4-中间件健康度数据.csv'),
            ('host', './data/5-主机健康度数据.csv')]

output_dir = "./output2"

sys_health_file = './data/6-系统健康度数据.csv'

out_put_file = "./数据修改方案记录表.xlsx"

modified_counts = [500, 500, 500, 300, 300, 300]

random_seed = 42

# 各个维度的系统健康度调整方向
# modify_method = [[("表空间使用率", "mean"), ("数据库锁数量", "min"), ("会话数", "mean"), "健康度"],
#                 [("业务量", "mean"), ("平均成功率", "mean"), ("平均时长", "min"), "健康度"],
#                 [("CPU使用率", "mean"), ("内存使用率", "mean"), ("响应时间", "mean"), "健康度"],
#                 [("请求数", "mean"), ("JVM内存使用率", "mean"), ("CPU使用率", "mean"), "健康度"],
#                 [("CPU使用率", "mean"), ("内存使用率", "mean"), ("文件系统使用率", "mean"), "健康度"]]

modify_method = {'db':{'columns':{'表空间使用率':'mean', "数据库锁数量":"min", "会话数":"mean"}, 'ref':'健康度'},
                 'bus':{'columns':{"业务量":"mean","平均成功率":"mean", "平均时长":"min"}, 'ref':'健康度'},
                 'app':{'columns':{"CPU使用率":"mean", "内存使用率":"mean", "响应时间":"mean"}, 'ref':'健康度'},
                 'mid':{'columns':{"请求数":"mean", "JVM内存使用率":"mean", "CPU使用率":"mean"}, 'ref':'健康度'},
                 'host':{'columns':{"CPU使用率":"mean", "内存使用率":"mean", "文件系统使用率":"mean"}, 'ref':'健康度'}}


def prepare():
    # 环境准备
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    else:
        os.system("rm -rf " + output_dir + "/*")
        os.system("rm -rf " + output_dir)
        os.makedirs(output_dir)




def main():
    # 修改记录
    modified_records_path = os.path.join(output_dir, "修改记录.csv")
    # modified_records_pd = pd.DataFrame(columns=("项目名", "数据文件名", "修改字段或位置", "计划修改前的值", "计划修改后的值","修改依据说明"))
    modified_records_pd = pd.DataFrame()
    # 获取各个维度的有修改字段的统计数据
    dim_statics_data = {}
    for dim_name, dim_file_path in data_files:
        columns = modify_method[dim_name]['columns'].keys()
        col_statics = _statics_data(dim_file_path, columns)
        dim_statics_data[dim_name] = col_statics
    # print(dim_statics_data)
    # 拆分6-系统健康度的文件
    # 目标是将数据拆分为6分
    # 以sys_health_file中的时刻为依据拆分为6分
    sys_health_df = pd.read_csv(sys_health_file)
    slice_length = math.floor(len(sys_health_df)/6)
    for idx in range(6):
        sliced_sys_health_floder_name = os.path.join(output_dir, str(idx+1))
        if not os.path.exists(sliced_sys_health_floder_name):
            os.makedirs(sliced_sys_health_floder_name)
        file_name = os.path.basename(sys_health_file).split(".")[0] + "-" + str(idx+1) + ".csv"
        file_path = os.path.join(sliced_sys_health_floder_name, file_name)

        # 获取写入文件的数据
        file_data_df = sys_health_df.loc[idx*slice_length:(idx+1)*slice_length -1]
        print("修改第{}份数据, 修改条数为-{}:".format(idx+1, modified_counts[idx]))
        for dim_name, dim_file_path in data_files:
            dim_df = pd.read_csv(dim_file_path)
            dim_file_name = os.path.basename(dim_file_path).split(".")[0] + "-" + str(idx+1) + ".csv"
            dim_out_file_path = os.path.join(sliced_sys_health_floder_name, dim_file_name)
            dataframes = []

            
            
            for timestap in file_data_df['时间']:
                # 取出改时间该维度下面的所有资源的记录
                df_timestap = dim_df[dim_df['时间']==timestap]
                dataframes.append(df_timestap)
                print("\r    维度:{} 查询进度:{:.2f}%".format(dim_name, (len(dataframes)/len(file_data_df))*100), end="", flush=True)
            df_picked = pd.concat(dataframes, axis=0)
            df_picked = df_picked.reset_index(drop=True)

            
            # 需要需改的条数
            m_counts = modified_counts[idx]
            print("    开始修改{}拆分的第{}分数据的前{}条数据:".format(dim_name, idx+1, m_counts))
            cols_processed = modify_method[dim_name]['columns'].keys()
            cols_record_origin = []
            for col in cols_processed:
                df_picked[col+'-原'] = None
                cols_record_origin.append(col+'-原')
            
            # 先记录下来需要修改的原始值
            df_picked.loc[0:m_counts-1, tuple(cols_record_origin)] = np.array(df_picked.loc[0:m_counts-1, tuple(cols_processed)])
            
            df_picked_modified = df_picked.loc[0:m_counts-1]
            
            # 随机一个需要修改的列
            # print(cols_processed)
            col_idx = random.randint(0, len(cols_processed)-1)
            _col_name = list(cols_processed)[col_idx]
            df_picked_modified[_col_name] = df_picked_modified.apply(dim_data_modify, axis=1, args=(dim_name, _col_name, modify_method, dim_statics_data))
            # for _col_name in cols_processed:
            #     df_picked_modified[_col_name] = df_picked_modified.apply(dim_data_modify, axis=1, args=(dim_name, _col_name, modify_method, dim_statics_data))
                
            df_picked.loc[0:m_counts-1, tuple(cols_processed)] = df_picked_modified.loc[:, tuple(cols_processed)]

            df_picked.to_csv(dim_out_file_path, index=False)
            print("    {} 第{}份数据修改完成".format(dim_file_path, idx+1))

            # 记录修改的数据
            print("    记录{} 第{}份数据修改字段".format(dim_file_path, idx+1))
            for index, row in df_picked_modified.iterrows():
                # print(dim_file_name, index, row, len(df_picked_modified))
                modify_info = "当前维度的健康度为{}".format(row['健康度'])
                modify_info += (">=85， 修改方向为减低健康度" if row['健康度'] >= 85.0 else "<85， 修改方向为提高健康度")
                # 数据文件名字段值
                if idx < 3:
                    dim_file_name_value = "第1轮/"+str(idx+1)+"/"+dim_file_name
                else:
                    dim_file_name_value = "第2轮(增加难度)/"+str(idx%3 + 1)+"/"+dim_file_name
                modified_records_pd = modified_records_pd.append({"项目名称": "集中化IT运维智能决策平台",
                                            "数据文件名": dim_file_name_value,
                                            "修改字段或位置": "第{}行, {}".format(index+1, _col_name),
                                            "计划修改前的值": row[_col_name+'-原'],
                                            "计划修改后的值": row[_col_name],
                                            "修改依据说明": modify_info
                                            }, ignore_index=True)
            modified_records_pd.to_csv(modified_records_path, index=True)




        # 将数据写入拆分的文件中
        file_data_df.to_csv(file_path, index=False)

def test():
    dim_statics_data = {'db': {'表空间使用率': {'mean': 0.39995952799999995, 'max': 0.918, 'min': 0.0}, '数据库锁数量': {'mean': 1999.52724, 'max': 2960, 'min': 1088}, '会话数': {'mean': 1199.562094, 'max': 2135, 'min': 189}}, 'bus': {'业务量': {'mean': 69.493567, 'max': 160, 'min': -19}, '平均成功率': {'mean': 79.529463, 'max': 188, 'min': -28}, '平均时长': {'mean': 999.554063, 'max': 1917, 'min': 6}}, 'app': {'CPU使用率': {'mean': 0.2008351999999999, 'max': 0.68, 'min': 0.0}, '内存使用率': {'mean': 0.30002766999999997, 'max': 0.77, 'min': 0.0}, '响应时间': {'mean': 199.527845, 'max': 283, 'min': 110}}, 'mid': {'请求数': {'mean': 299.521691, 'max': 401, 'min': 191}, 'JVM内存使用率': {'mean': 0.7988688899999999, 'max': 0.99, 'min': 0.34}, 'CPU使用率': {'mean': 0.20076560999999996, 'max': 0.68, 'min': 0.0}}, 'host': {'CPU使用率': {'mean': 0.20086063999999992, 'max': 0.66, 'min': 0.0}, '内存使用率': {'mean': 0.30006355999999995, 'max': 0.84, 'min': 0.0}, '文件系统使用率': {'mean': 0.49991740000000007, 'max': 0.99, 'min': 0.01}}}

    dim_file = './data/1-数据库健康度数据.csv'
    dim_name = 'db'
    df_picked = pd.read_csv(dim_file)[0:100]
    # df_picked_modified = df_picked[0:500].copy()
    
    cols_processed = modify_method[dim_name]['columns'].keys()
    cols_record_origin = []
    for col in cols_processed:
        df_picked[col+'-原'] = None
        cols_record_origin.append(col+'-原')

    df_picked.loc[0:10, tuple(cols_record_origin)] = np.array(df_picked.loc[0:10, tuple(cols_processed)])

    # 获取需要了修改的df
    df_picked_modified = df_picked.loc[0:10]
    for col in cols_processed:
        df_picked_modified[col] = df_picked_modified.apply(dim_data_modify, axis=1, args=(dim_name, col, modify_method, dim_statics_data))
    
    df_picked.loc[0:10, tuple(cols_processed)] = df_picked_modified.loc[:, tuple(cols_processed)]

    df_picked.to_csv("./test.csv", index=False)

def dim_data_modify(row_item, dim_name, col_name, _dim_modify_method, _dim_statics_data):

    # 返回的修改值
    data=[]
    # 修改方法
    modify_m = _dim_modify_method[dim_name]
    # 统计数据
    statics_data = _dim_statics_data[dim_name]
    # 获取当前维度的系统健康度
    health_value = row_item[modify_m['ref']]
    # for col_name, c_direction in modify_m['columns'].items():
    #     # 获取当前列的值和方向目标值
    #     col_value = row_item[col_name]
    #     mean_value = statics_data[col_name]['mean']
    #     max_value = statics_data[col_name]['max']
    #     min_value = statics_data[col_name]['min']
    #     if c_direction == "mean":
    #         if health_value >= 85:
    #             # 降低健康度的方向
    #             value = max_value if max_value - mean_value >= mean_value - min_value else min_value
    #             row_item[col_name] = value
    #         else:
    #             # 提升健康度的方法
    #             row_item[col_name] = mean_value
    #     elif c_direction == "max":
    #         if health_value >= 85:
    #             # 降低健康度的方向
    #             row_item[col_name] = min_value
    #         else:
    #             # 提升健康度的方法
    #             row_item[col_name] = max_value
    #     elif c_direction == "min":
    #         if health_value >= 85:
    #             # 降低健康度的方向
    #             row_item[col_name] = max_value
    #         else:
    #             # 提升健康度的方法
    #             row_item[col_name] = min_value
    #     else:
    #         pass

    # 获取当前列的值和方向目标值
    c_direction =  modify_m['columns'][col_name]
    col_value = row_item[col_name]
    mean_value = statics_data[col_name]['mean']
    max_value = statics_data[col_name]['max']
    min_value = statics_data[col_name]['min']
    if c_direction == "mean":
        if health_value >= 85:
            # 降低健康度的方向
            # value = max_value if max_value - mean_value >= mean_value - min_value else min_value
            col_value_mean_dis = abs(col_value - mean_value)
            value = min(max_value, col_value + 0.1*col_value_mean_dis) if col_value >= mean_value else max(min_value, col_value - 0.1*col_value_mean_dis)

            row_item[col_name] = value
        else:
            # 提升健康度的方法
            col_value_mean_dis = abs(col_value - mean_value)
            value = max(min_value, col_value - 0.1*col_value_mean_dis) if col_value >= mean_value else min(max_value, col_value + 0.1*col_value_mean_dis)
            row_item[col_name] = mean_value
    elif c_direction == "max":
        if health_value >= 85:
            # 降低健康度的方向
            # row_item[col_name] = min_value
            row_item[col_name] = col_value * 0.9
        else:
            # 提升健康度的方法
            # row_item[col_name] = max_value
            row_item[col_name] = min(max_value, col_value * 1.1)
    elif c_direction == "min":
        if health_value >= 85:
            # 降低健康度的方向
            # row_item[col_name] = max_value
            row_item[col_name] = min(max_value, col_value * 1.1)
        else:
            # 提升健康度的方法
            # row_item[col_name] = min_value
            row_item[col_name] = col_value * 0.9
    else:
        pass
    
    return row_item[col_name]



def _statics_data(file_path, columns):
    dim_df = pd.read_csv(file_path)
    res_data = {}
    for col in columns:
        data ={}
        data['mean'] = dim_df[col].mean()
        data['max'] = dim_df[col].max()
        data['min'] = dim_df[col].min()
        data['health_mean'] = dim_df["健康度"].mean()
        data['health_max'] = dim_df["健康度"].max()
        data['health_min'] = dim_df["健康度"].min()
        res_data[col] = data
    return res_data


if __name__ == "__main__":
    prepare()
    main()
    # test()
